package com.four.project.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @Author zyt
 * @create 2020/7/7 10:59
 */

@Slf4j
@Controller
@RequestMapping("/alipay")
public class PayController {
        // 应用ID,您的APPID，收款账号既是您的APPID对应支付宝账号
        public static String app_id = "2016102600764074";

        // 商户私钥，您的PKCS8格式RSA2私钥
        public static String merchant_private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCivlybfYC9+tu/N1ZHA/OM2W6K+j99QvVr+HPzGIvoZZ9obaWugM+Sd4rxT2FVEXtmqeSK1mnK9O4CyiryOGQ9vEXkwtpIrSgRP6iqPPlBYjlb6Uin6dpPdC9R+oAhnCTExMe73fUJg3UHO6yRT5Iebitz25cWEQ1fJUDikq9l6bP4JWoDWY6rCCl6Syu0N9eQ5O2xtEOYkK5J2XsVZNVc/eit/h2vhThxMcLqRRd4u1gqW4AND/o6xMDFfJ62fsaxjJ7qX0uuyKNxUtr8ZAmCcQPjsYC025Uvlst7Cbsu4VQqhMZ2Z0UkllFo7+iMKRW38UB2ofiT8Kt3iNjO4moTAgMBAAECggEATZdQ89lcXjeSOZKakfUyUz7/U0eIqaIY/MdSEN7tJXn+DH3qdk53qK9SEUb1cueI3CO4EPG1MsygBbh5zU5RjJWNBUpZZDkaV07wjWnQtPmtu0J4H4aBTUxpmz5BhMS7Sw0+5TUntMd2LmKnHgi/8742/V/+osiyhWBvlRa2hXGpF4Rbu8izFSHKhuV0Kh1qMYztLb0usxpjABraZJ6PZzgRLM65Ihk+u4QAVJ16F27GLhLQD8fgH9kmPr7Jrb8wnCjzJJIxxA2p8QZVD5ebHV7KZSGnwnz6AF9YECBMISE7alPrtUTTDE04n4h59+mWWaZlLsXGgNY7B2m9XpZx4QKBgQDl5QQPQz/d7Lgu/V90z7872zqn8HOEDJ/NVXsoDJuidKHGO2JNKV7gr/FVZap6ohhfkszft+FNrDxsZEm718tq+B/niyID2j7rHl4dkSTrK07y1s7toWorjKLRYVHQJSE2Z4XbVPFpZLeXAtjy/D06Cb++m0zy2vgIn3uJm9tlmwKBgQC1OUgY7SA0eP34BkC3gJW9fWcIywyBeUjfCIp7FhVpEMW5LR21JwqxUKgi/Syn+Th28DKiNlgdgiaNkWoi+/3pgI1YwzuXDhMAtlGuYIp9ID2MSnJ8fqa2bVfUjEEZtdvercf98tZrSFCamoQk1TjFtoLsRl/onaZMDLocWb/Q6QKBgGbWHw7Ewlj/fxRl+sFB/QVFd+OPx9yV2RX82u57VVNCYOtPvRVPIEXZ7laI982LnOODw2l/06TvGshRxDnmufPLslnc/wZCJkr+dpM7Tgx0fwhZ1o6t2dRJQLvwkKxPL6AqhtIqGSNQDl/awjlPZAQGQGN/DNjF4pXY4WYY9fdpAoGABiqaz25SKDbtvWDJFvVjIv1/Ygc2t7kex6gMvj90Hw0ZDUIBvsZDUOFDt10SBe0vBK0LrAVZXjethCesiuA0NZvQM3MBNhSehOmvQdW7IKLWNU3bM21D0vVJhcv38x4DC0KyiWuX7DKbu4cCdBZlRiT9s3h5jvq+S9wrAQf0xPECgYEAyV7993tjKFoLIaB7ma02LgLeQ0qrpQUMFF3tjSgLie4S2zQbYkvmgtuJIXbf9wrtmZtPOdLFt2M99TxQynR+cbawwyg9mihjOCTUEmoKjm7ufWeoKngJM3wu+h7wRVWV+bBvrAMyGr+ruMw284Zg2X7xZHe1lEYWZVKKY19IMn8=";

        // 支付宝公钥,查看地址：https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
        public static String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAor5cm32AvfrbvzdWRwPzjNluivo/fUL1a/hz8xiL6GWfaG2lroDPkneK8U9hVRF7ZqnkitZpyvTuAsoq8jhkPbxF5MLaSK0oET+oqjz5QWI5W+lIp+naT3QvUfqAIZwkxMTHu931CYN1BzuskU+SHm4rc9uXFhENXyVA4pKvZemz+CVqA1mOqwgpeksrtDfXkOTtsbRDmJCuSdl7FWTVXP3orf4dr4U4cTHC6kUXeLtYKluADQ/6OsTAxXyetn7GsYye6l9LrsijcVLa/GQJgnED47GAtNuVL5bLewm7LuFUKoTGdmdFJJZRaO/ojCkVt/FAdqH4k/Crd4jYzuJqEwIDAQAB";

        // 服务器异步通知页面路径 需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
        public static String notify_url = "http://localhost:8080/alipay/notifyUrl";

        // 页面跳转同步通知页面路径 需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问
        public static String return_url = "http://localhost:8080/alipay/returnUrl";

        // 签名方式
        public static String sign_type = "RSA2";

        // 字符编码格式
        public static String charset = "utf-8";

        //沙箱网关
        public static String gatewayUrl ="https://openapi.alipaydev.com/gateway.do";

        // 仅支持JSON
        public static String format = "JSON";


    @ApiOperation(value = "发起支付", notes = "支付宝")
    @RequestMapping(value = "/pay")
    @ResponseBody
    public void pay(/*@RequestParam("orderNo") String orderNo, @RequestParam("totalPrice") String totalPrice,
                    @RequestParam("itemString") String itemString,*/ HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException {

        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, app_id, merchant_private_key, format, charset, alipay_public_key, sign_type);  //获得初始化的AlipayClient

        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); //创建API对应的request
        alipayRequest.setReturnUrl(return_url);
        alipayRequest.setNotifyUrl(notify_url); //在公共参数中设置回跳和通知地址
        //alipayRequest.putOtherTextParam("app_auth_token", "201611BB8xxxxxxxxxxxxxxxxxxxedcecde6");//如果 ISV 代商家接入电脑网站支付能力，则需要传入 app_auth_token，使用第三方应用授权；自研开发模式请忽略

        //商户订单号，商户网站订单系统中唯一订单号，必填
       // String out_trade_no = httpRequest.getParameter("1321323143414");
        //付款金额，必填  ShopName
        //String total_amount = httpRequest.getParameter("Money");
        //订单名称，必填
        //String subject = httpRequest.getParameter("Name");
        //商品描述，可空
        //String body =httpRequest.getParameter("购物测试");

        //设置订单允许最晚付款时间
        String timeout_express="1c";

        alipayRequest.setBizContent("{" +
                "    \"out_trade_no\":\"20150323101010017\","  +
                "    \"product_code\":\"FAST_INSTANT_TRADE_PAY\","  +
                "    \"total_amount\":88.88,"  +
                "    \"subject\":\"Iphone6 16G\","  +
                "    \"body\":\"Iphone6 16G\","  +
                "    \"passback_params\":\"merchantBizType%3d3C%26merchantBizNo%3d2016010101111\"," +
                "    \"extend_params\":{" +
                "    \"timeout_express\":\""+ timeout_express +"\","+
                "    \"sys_service_provider_id\":\"2088511833207846\"" +
                "    }" +
                "  }"); //填充业务参数
        String form = "";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody();  //调用SDK生成表单

            httpResponse.setContentType("text/html;charset=" + "utf-8");
            httpResponse.getWriter().write(form); //直接将完整的表单html输出到页面
            httpResponse.getWriter().flush();
            httpResponse.getWriter().close();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        System.out.println(form);
        //return form;
    }

    @ApiOperation(value = "支付同步回调", notes = "支付宝")
    @RequestMapping(value = "/returnUrl", method = RequestMethod.GET)
    public void returnUrl(HttpServletRequest request, HttpServletResponse response)
            throws IOException, AlipayApiException {
        System.out.println("=================================同步回调=====================================");

        // 获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        System.out.println(params);
        boolean signVerified =  AlipaySignature.rsaCheckV1(params, alipay_public_key, charset, sign_type);

        // ——请在这里编写您的程序（以下代码仅作参考）——
        if (signVerified) {
            // 商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");

            System.out.println("商户订单号="+out_trade_no);
            System.out.println("支付宝交易号="+trade_no);
            System.out.println("付款金额="+total_amount);

            response.getWriter().write(
                    "trade_no:" + trade_no + "<br/>out_trade_no:" + out_trade_no + "<br/>total_amount:" + total_amount);
        } else {
            response.getWriter().write("验签失败");
        }
        response.getWriter().flush();
        response.getWriter().close();
    }


    @ApiOperation(value = "支付异步回调", notes = "支付宝")
    @RequestMapping(value = "/notifyUrl", method = RequestMethod.POST)
    public void notifyUrl(HttpServletRequest request, HttpServletResponse response)
            throws AlipayApiException, IOException {
        System.out.println("#################################异步回调######################################");

        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        System.out.println(params);
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipay_public_key, charset, sign_type); // 调用SDK验证签名

        // ——请在这里编写您的程序（以下代码仅作参考）——

        /*
         * 实际验证过程建议商户务必添加以下校验： 1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
         * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额）， 3、校验通知中的seller_id（或者seller_email)
         * 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
         * 4、验证app_id是否为该商户本身。
         */
        if (signVerified) {// 验证成功
            // 商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");

            System.out.println("商户订单号="+out_trade_no);
            System.out.println("支付宝交易号="+trade_no);
            System.out.println("交易状态="+trade_status);
            /*if (trade_status.equals("TRADE_FINISHED")) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                // 如果有做过处理，不执行商户的业务程序

                // 注意：
                // 退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            } else if (trade_status.equals("TRADE_SUCCESS")) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                // 如果有做过处理，不执行商户的业务程序

                // 注意：
                // 付款完成后，支付宝系统发送该交易状态通知
            }*/
            System.out.println("异步回调验证成功");

            //修改数据库


            response.getWriter().write("success");

        } else {// 验证失败
            System.out.println("异步回调验证失败");
            response.getWriter().write("fail");

            // 调试用，写文本函数记录程序运行情况是否正常
            // String sWord = AlipaySignature.getSignCheckContentV1(params);
            // AlipayConfig.logResult(sWord);
        }
        response.getWriter().flush();
        response.getWriter().close();
    }

}
